package com.youlai.mrp.service;

import com.youlai.common.base.PageBean;
import com.youlai.eng.entity.EngBill2Entity;
import com.youlai.eng.entity.EngItemEntity;
import com.youlai.mrp.query.BaseQuery;
import com.youlai.mrp.query.PageQuery;
import com.youlai.eng.repository.EngItemRepository;
import com.youlai.eng.service.EngBill2Service;
import com.youlai.eng.service.EngItemService;
import com.youlai.mrp.entity.MrpFccotableEntity;
import com.youlai.mrp.entity.MrpTableEntity;
import com.youlai.mrp.repository.MrpTableRepository;
import com.youlai.common.base.BaseService;
import com.youlai.common.model.Option;
import com.youlai.common.result.PageResult;
import com.youlai.common.result.Result;
import com.youlai.sale.entity.SaleCoDetailEntity;
import com.youlai.sale.entity.SaleItemForecastEntity;
import com.youlai.sale.repository.SaleItemForecastRepository;
import com.youlai.utils.DateUtils;
import com.youlai.utils.IdWorker;
import com.youlai.system.util.SecurityUtils;
import com.youlai.core.security.model.SysUserDetails;
import com.youlai.system.service.SysDictService;
import jakarta.annotation.Resource;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class MrpTableService extends BaseService<MrpTableEntity> {
    @Autowired
    private MrpTableRepository repository;

    @Autowired
    EngItemService engItemService;

    @Autowired
    private EngItemRepository engItemRepository;
    @Autowired
    SaleItemForecastRepository saleItemForecastRepository;

    @Autowired
    MrpFccoTableService mrpFccoTableService;

    @PersistenceContext
    private EntityManager em;

    public EntityManager getEntityManager() {
        return em;
    }

    @Resource
    SysDictService sysDictService;

    @org.springframework.transaction.annotation.Transactional(rollbackFor = Exception.class)
    public Result<MrpTableEntity> runMrp(MrpTableEntity entity) {
        //提取还没有过期的预测（Forecast）剩余
        String hql = " from SaleItemForecastEntity  where 1=1";
//        if (StringUtils.isNotEmpty(entity.getItemNo())  ) {
//            hql += " and itemNo like '%" + entity.getItemNo() +"%'";
//        }
        hql += " and isFinish =0  ";
        hql += " order by forecastDate asc  ";
        Query query = em.createQuery(hql);

        List<SaleItemForecastEntity> list = query.getResultList();
        for(SaleItemForecastEntity o:list) {
            if(o.getForecastQty() > o.getConsumeQty()) {
                EngItemEntity engItemEntity = engItemRepository.findTopByItemNoAndDeleted(o.getItemNo(),0);
                Integer leadTime = engItemEntity.getLeadTime();
                if(leadTime==null) {
                    leadTime = 0;
                }
                Date forecastDate  = o.getForecastDate();
                Date forecastDate2 = DateUtils.addDay(forecastDate,leadTime);

                double originalDemandQty  = o.getForecastQty() - o.getConsumeQty();
                MrpFccotableEntity mrpFccotableEntity = new MrpFccotableEntity();
                mrpFccotableEntity.setItemNo(o.getItemNo());
                mrpFccotableEntity.setLevel(0);
                mrpFccotableEntity.setOriginalDemandDate(o.getForecastDate());
                mrpFccotableEntity.setOriginalDemandQty(originalDemandQty);
                mrpFccotableEntity.setSource("FC");
                mrpFccotableEntity.setSourceNo(DateUtils.dateToString(o.getForecastDate()));
                mrpFccotableEntity.setIsFinish(0);
                mrpFccoTableService.save(mrpFccotableEntity);
            }
        }

        //客户订单（CO）欠数
        hql = " from SaleCoDetailEntity t where 1=1";
        hql += " and isFinish =0  ";
        hql += " order by t.deliveryDate  ";
        query = em.createQuery(hql);
        List<SaleCoDetailEntity> list2 = query.getResultList();
        for(SaleCoDetailEntity o:list2) {
            if(o.getCoQty() > o.getDelQty()) {
                EngItemEntity engItemEntity = engItemRepository.findTopByItemNoAndDeleted(o.getItemNo(),0);
                Integer leadTime = engItemEntity.getLeadTime();
                if(leadTime==null) {
                    leadTime = 0;
                }
                Date deliveryDate  = o.getDeliveryDate();
                Date forecastDate2 = DateUtils.addDay(deliveryDate,leadTime);

                double originalDemandQty  = o.getCoQty() - o.getDelQty();
                MrpFccotableEntity mrpFccotableEntity = new MrpFccotableEntity();
                mrpFccotableEntity.setItemNo(o.getItemNo());
                mrpFccotableEntity.setLevel(0);
                mrpFccotableEntity.setOriginalDemandDate(deliveryDate);
                mrpFccotableEntity.setOriginalDemandQty(originalDemandQty);
                mrpFccotableEntity.setSource("CO");
                mrpFccotableEntity.setSourceNo(o.getCoNo());
                mrpFccotableEntity.setIsFinish(0);
                mrpFccoTableService.save(mrpFccotableEntity);
            }
        }


        MrpFccotableEntity mrpFccotableEntity = new MrpFccotableEntity();
        mrpFccotableEntity.setIsFinish(0);
        List<MrpFccotableEntity> list3 = mrpFccoTableService.findListBy(mrpFccotableEntity);
        for(MrpFccotableEntity o:list3) {
            MrpTableEntity mrpTableEntity = new MrpTableEntity();
            mrpTableEntity.setItemNo(o.getItemNo());
            mrpTableEntity.setLevel(0);
            mrpTableEntity.setSource(o.getSource());
            mrpTableEntity.setSourceNo(o.getSourceNo());
            mrpTableEntity.setDemandQty(o.getOriginalDemandQty());
            mrpTableEntity.setSdDate(o.getOriginalDemandDate());
            mrpTableEntity.setOrderSupplyQty(0d);
            mrpTableEntity.setStoreSupplyQty(0d);
            this.save(mrpTableEntity);

            // 后再提取相应的物料清单（BOM）
            Double originalDemandQty = o.getOriginalDemandQty();
            EngBill2Entity engBill2Entity = new EngBill2Entity();
            engBill2Entity.setParentItemNo(o.getItemNo());
            List<EngBill2Entity> list11 = engBill2Service.findListBy(engBill2Entity);
            genChildBill(list11,o,originalDemandQty);
        }

        return  null;
    }

    /**
     这里的one代表的是初始第一根柱子
     two代表的是中转盘子的第二根柱子
     three代表的是目的柱子
     */
    public  void genChildBill( List<EngBill2Entity> list11,MrpFccotableEntity fccotableEntity,Double originalDemandQty){
        if(list11==null) {
            return;
        }
        if(list11!=null && list11.size()==0){
            return;
        }else{
            for(EngBill2Entity o2:list11) {
                if( o2.getItemNoEntity()!=null) {
                    Integer orderPolicy = o2.getItemNoEntity().getOrderPolicy();
                    if(orderPolicy!=null && orderPolicy==2) {

                    }else {
                        continue;
                    }
                }else {
                    continue;
                }

                String ct= o2.getCt();
                if(StringUtils.isNotEmpty(ct) && ct.equals("C")) { //回收料不处理
                    continue;
                }
                MrpTableEntity mrpTableEntity = new MrpTableEntity();
                mrpTableEntity.setItemNo(o2.getItemNoEntity().getItemNo());
                mrpTableEntity.setLevel(1);
                mrpTableEntity.setSource(fccotableEntity.getSource());
                mrpTableEntity.setSourceNo(fccotableEntity.getSourceNo());
                mrpTableEntity.setDemandQty(o2.getQty()*originalDemandQty);
                mrpTableEntity.setSdDate(fccotableEntity.getOriginalDemandDate());
                mrpTableEntity.setOrderSupplyQty(0d);
                mrpTableEntity.setStoreSupplyQty(0d);
                this.save(mrpTableEntity);

                Double originalDemandQty2 = fccotableEntity.getOriginalDemandQty();

                //处理子货号
                EngItemEntity engItemEntity = o2.getItemNoEntity();
                EngBill2Entity engBill2Entity = new EngBill2Entity();
                engBill2Entity.setParentItemNo(engItemEntity.getItemNo());
                List<EngBill2Entity> list12 = engBill2Service.findListBy(engBill2Entity);
                genChildBill(list12,fccotableEntity,o2.getQty()*originalDemandQty2);
            }
        }
    }

    @Resource
    EngBill2Service engBill2Service;

    /**
     * 分页查询列表
     *
     * @param queryParams
     * @return
     */
    public PageResult<MrpTableEntity> getPageByHql(PageQuery queryParams) {
        String keywords = queryParams.getKeywords();
        // 动态拼接sql
        String hql = "from MrpTableEntity t where 1=1 and deleted = 0 ";
        if (StringUtils.isNotEmpty(keywords)) {
            hql += " and (" +
                    " itemNo like '%" + keywords + "%' " +
                    " or source like '%" + keywords + "%' " +
                    ") ";
        }

        // 查询参数
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();

        DateUtils.toDatabaseFormat(queryParams, "startUpdateTime", "endUpdateTime");
        if (StringUtils.isNotEmpty(queryParams.getStartUpdateTime())) {
            hql += " and DATE_FORMAT(t.updateTime, '%Y-%m-%d %H:%i:%s') >=  '"+ queryParams.getStartUpdateTime()  +"'  ";
        }
        if (StringUtils.isNotEmpty(queryParams.getEndUpdateTime())) {
            hql += " and DATE_FORMAT(t.updateTime, '%Y-%m-%d %H:%i:%s') <=  '"+ queryParams.getEndUpdateTime()  +"'  ";
        }

        // 查询数据
        PageBean pageBean = new PageBean();
        pageBean.setPage(pageNum);
        pageBean.setRows(pageSize);
        String countHql = getCountHql(hql);
        Query countQuery = em.createQuery(countHql);
        pageBean.setTotal(countQuery.getSingleResult().toString());

        hql += " order by  t.level desc, t.itemNo, t.sdDate ";
        Query query = em.createQuery(hql);
        query.setFirstResult(pageBean.getStartIndex());
        query.setMaxResults(pageBean.getRows());
        List<MrpTableEntity> list = query.getResultList();
        for(MrpTableEntity o:list) {
            EngItemEntity engItemEntity = engItemRepository.findTopByItemNoAndDeleted(o.getItemNo(),0);
            o.setEngItemEntity(engItemEntity);
        }
        PageResult page = PageResult.success(list, pageBean.getTotal());
        return page;
    }

    public Result<MrpTableEntity> save(MrpTableEntity entity) {
        boolean isCreate = false;
        if(entity.getMrpTableId()==null) {
            isCreate = true;
            entity.setMrpTableId(IdWorker.generateId());
        }
        return super.save(entity, isCreate);
    }

    protected void beforeSave(MrpTableEntity  entity, Boolean isCreate){
        // 校验员工编号是否存在
//        String itemNo = entity.getItemNo();
//        Specification<MrpTableEntity> spec = (Root<MrpTableEntity> root, CriteriaQuery<?> cq, CriteriaBuilder cb) -> {
//            Predicate predicate = cb.and(cb.equal(root.get("itemNo"), itemNo));
//            predicate = cb.and(cb.notEqual(root.get("saleItemId"), entity.getMrpTableId()),predicate);
//            return predicate;
//        };
//        long count = repository.count(spec);
//        Assert.isTrue(count == 0, "地址编号已存在");

        super.beforeSave(entity,isCreate);
    }

    public MrpTableEntity findById(Long id){
        Optional<MrpTableEntity> optional  = repository.findById(id);
        if(optional.isPresent()) {
            return optional.get();
        }
        return null;
    }


    public List<MrpTableEntity> findListBy(MrpTableEntity entity){
        // 动态拼接sql
        String hql = "select * from MrpTableEntity where 1=1";
        if (StringUtils.isNotEmpty(entity.getItemNo())  ) {
            hql += " and customerNo like '%" + entity.getItemNo() +"%'";
        }
        hql += "  ";
        return super.findListBy(entity,hql);
    }

    public Boolean deleteAllById(String idStrs){
        SysUserDetails user = SecurityUtils.getUser();
        // 逻辑删除
        List<Long> ids = Arrays.asList(idStrs.split(",")).stream()
                .map(idStr -> Long.parseLong(idStr)).collect(Collectors.toList());
        for(Long id:ids) {
            Optional<MrpTableEntity> optional  = repository.findById(id);
            if(optional.isPresent()) {
                MrpTableEntity entity = optional.get();
                entity.setDeleted(1);

                entity.setUpdateBy(user.getUserId());
                entity.setUpdateName(user.getUsername());
                repository.save(entity);
            }
        }
        return true;
    }

    public List<Option> listEngEmpOptions(BaseQuery baseQuery) {
        Specification<MrpTableEntity> spec  = (Root<MrpTableEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) -> {
            Predicate predicate = cb.and(cb.equal(root.get("status"), 1));
            predicate = cb.and(cb.equal(root.get("deleted"), 0), predicate);
            return predicate;
        };
        List<MrpTableEntity> list = repository.findAll(spec);
        List<Option> lastList = new ArrayList<>();
        for(MrpTableEntity o:list) {
            Option option = new Option<String>();
            option.setLabel(o.getSourceNo());
            option.setValue(o.getItemNo());
            lastList.add(option);
        }
        return lastList;
    }

}


